<?php

namespace app\common;

use app\common\Error;
use think\exception\HttpResponseException;
// use think\facade\Db;
use think\facade\Cache;

class Common
{
    /**
     * 正常响应
     *
     * @dateTime 2022/09/01
     * @author zhixiang0215@126.com
     * @param array|object data 响应数据
     * @param string message 响应提示
     * @return
     */
    public static function success($data = [], string $message = Error::SUCCESS_MESSAGE)
    {
        return json([
            'code' => Error::SUCCESS_CODE,
            'message' => $message,
            'data' => $data
        ]);
    }

    /**
     * 异常响应
     *
     * @dateTime 2022/09/01
     * @author zhixiang0215@126.com
     * @param array data 响应数据
     * @param string message 响应提示
     * @param int code 状态码标识
     * @return
     */
    public static function fail(string $message = Error::FAIL_MESSAGE, int $code = Error::FAIL_CODE, $data = [])
    {
        return json([
            'code' => $code,
            'message' => $message,
            'data' => $data
        ]);
    }

    /**
     * 自定义重定向方法 重要的操作二
     * @param $args
     */
    public static function redirect(...$args)
    {
        // 此处 throw new HttpResponseException 这个异常一定要写
        throw new HttpResponseException(redirect(...$args));
    }

    /**
     * 通用curl操作
     *
     * @dateTime 2022/09/01
     * @author zhixiang0215@126.com
     * @param string url 请求地址
     * @param json|array data 请求数据
     * @param string type 请求类型
     * @param array options 请求头/报文信息
     * @return
     */
    public static function _curl($url, $data = '', $type = 'POST', $options = [])
    {
        if (empty($url)) return false;

        $type = in_array(strtoupper($type), ['POST', 'GET', 'PUT', 'PATCH', 'DELETE']) ? strtoupper($type) : 'POST';

        $connectTimeout = isset($options['connect_timeout']) ? $options['connect_timeout'] : 60;
        $curloptTimeout = isset($options['curlopt_timeout']) ? $options['curlopt_timeout'] : 30;

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_ENCODING, ''); // 编码格式
        curl_setopt($ch, CURLOPT_AUTOREFERER, 1);   // 自动设置Referer
        curl_setopt($ch, CURLOPT_FAILONERROR, false);   // 不显示400等错误详情
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 获取的信息以字符串返回
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connectTimeout); // 尝试连接时等待的秒数，0不限制
        curl_setopt($ch, CURLOPT_TIMEOUT, $curloptTimeout);    // 允许 cURL 函数执行的最长秒数
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 允许自动进行跳转抓取
        curl_setopt($ch, CURLOPT_MAXREDIRS, 10);    // 最多允许跳转多少次
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);  // 使用的HTTP协议

        // curl_setopt($ch, CURLOPT_HEADER, true); // 返回response头部信息
        curl_setopt($ch, CURLINFO_HEADER_OUT, true); // TRUE 时追踪句柄的请求字符串，从 PHP 5.1.3 开始可用。这个很关键，就是允许你查看请求header

        if (isset($options['ua'])) {
            curl_setopt($ch, CURLOPT_USERAGENT, (is_bool($options['ua']) ? 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36' : $options['ua']) );
        }

        if (isset($options['curlopt_timeout_ms'])) {
            curl_setopt($ch, CURLOPT_TIMEOUT_MS, $options['curlopt_timeout_ms']); // 允许 cURL 函数执行的最长毫秒数
        }

        // https 请求
        if (strlen($url) > 5 && strtolower(substr($url, 0, 5)) == 'https') {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        }

        if (isset($options['headers']) || isset($options['json'])) {
            $headers = isset($options['headers']) ? (is_array($options['headers']) ? $options['headers'] : [$options['headers']]) : [];

            if (isset($options['json'])) {
                $headers[] = 'Content-Type: application/json';
                $headers[] = 'cache-control: no-cache';
            }

            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }

        switch (strtoupper($type)) {
            case 'GET':
                curl_setopt($ch, CURLOPT_HTTPGET, true);
                $data = empty($data) ? '' : (is_array($data) ? http_build_query($data) : $data);
                $url .= strrchr($url, '?') === false ? (empty($data) ? '' : '?' . $data) : '&' . $data;
                break;

            default :
                if ($type == 'POST') {
                    curl_setopt($ch, CURLOPT_POST, true);
                } else {
                    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $type);
                }

                if (isset($options['json']) && is_array($data)) {
                    $data = json_encode($data);
                }
                curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        }

        curl_setopt($ch, CURLOPT_URL, $url);

        $result = curl_exec($ch); // 获得返回值
        //dump(curl_getinfo($ch));//获取连接资源句柄的信息
        curl_close($ch);

        return $result;
    }

    /**
     * 使用curl完成对接口的请求
     * @param $url :接口的url地址
     * @param string $type :传输类型,若为POST需要提供$data与$header
     * @param string $data :当type = POST时需要提供,为请求主体数据
     * @param array $header :当type = POST时需要提供,为请求头
     * @return bool|string
     */
    public static function curlRequest($url, string $type = '', string $data = '', array $header = [])
    {
        $action = curl_init();
        curl_setopt($action, CURLOPT_URL, $url);
        curl_setopt($action, CURLOPT_CONNECTTIMEOUT, 60);
        curl_setopt($action, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($action, CURLOPT_HEADER, 0);
        curl_setopt($action, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($action, CURLOPT_SSL_VERIFYHOST, 0);
        if ($type == 'POST') {
            curl_setopt($action, CURLOPT_POST, 1);
            curl_setopt($action, CURLOPT_POSTFIELDS, $data);
        }
        if(!empty($header)){
            curl_setopt($action, CURLOPT_HTTPHEADER, $header);
        }
        $result = curl_exec($action);
        curl_close($action);
        return $result;
    }

    /**
     * curl get 请求带header
     *
     * @param $url string 请求地址
     * @param $data string 参数数据
     * @param $header array 请求头
     * @return json
     */
    public static function curlGetRequest($url, $data, array $hearder = [])
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_USERAGENT, 'Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12.388 Version/12.15');
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // stop verifying certificate
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $hearder);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
        $result = curl_exec($curl);
        curl_close($curl);
        return $result;
    }

    // curl post 请求带header
    public static function curlPostRequest($url, $data, array $hearder = [])
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $hearder);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
        $result = curl_exec($curl);
        curl_close($curl);
        return $result;
    }

    // curl post 请求带header
    public static function curlGetRequestHeader($url, array $header = [])
    {
        $action = curl_init();
        curl_setopt($action, CURLOPT_URL, $url);
        curl_setopt($action, CURLOPT_CONNECTTIMEOUT, 60);
        curl_setopt($action, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($action, CURLOPT_HEADER, 0);
        curl_setopt($action, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($action, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($action, CURLOPT_HTTPHEADER, $header);
        $result = curl_exec($action);
        curl_close($action);
        return $result;
    }

    /**
     * 生成token
     *
     * @dateTime 2022/09/01
     * @author zhixiang0215@126.com
     * @param int $userId
     * @return string
     */
    public static function createToken(int $userId)
    {
        // 当前时间戳 (精确到毫秒)
        $timeStamp = microtime(true);
        // 自定义一个盐
        $salt = 'video';
        $guid = uniqid();

        return md5("{$timeStamp}_{$userId}_{$guid}_{$salt}");
    }

    /**
     * 获取真实IP
     * @param int $type
     * @param bool $client
     * @return mixed
     */
    public static function getClientIp($type = 0, $client = true)
    {
        $type = $type ? 1 : 0;
        static $ip = NULL;
        if ($ip !== NULL) return $ip[$type];
        if ($client) {
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                $pos = array_search('unknown',$arr);
                if(false !== $pos) unset($arr[$pos]);
                $ip  = trim($arr[0]);
            } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
                $ip = $_SERVER['HTTP_CLIENT_IP'];
            } elseif (isset($_SERVER['REMOTE_ADDR'])) {
                $ip = $_SERVER['REMOTE_ADDR'];
            }
        } elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        // 防止IP伪造
        $long = sprintf("%u", ip2long($ip));
        $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
        return $ip[$type];
    }

    // 获取32位随机串
    public static function nonceStr($length)
    {
        $string = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
        $res = '';

        for ($i = 0; $i < $length ; $i++) {
            shuffle($string);
            $res .= $string[$i];
        }

        return $res;
    }

    // 获取毫秒时间戳
    public static function msectime()
    {
        list($msec, $sec) = explode(' ', microtime());
        $msectime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
        return intval($msectime);
    }

    // 获取公众号关注二维码地址
    public static function getOfficialAccountFollowQrcodeUrl($officialAccountData, $uid)
    {
        // 获取access_token
        $accessToken = self::getWechatOfficialAccountAccessToken($officialAccountData['app_id'], $officialAccountData['app_secret'], $officialAccountData['id']);

        if (empty($accessToken)) {
            return false;
        }

        $qrcodeUrl = 'https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token='.$accessToken;

        $postArr =  [
            'action_name' => 'QR_STR_SCENE',
            'expire_seconds' => 604800,
            'action_info' => [
                'scene' => ['scene_str' => "$uid"],
            ]
        ];

        // file_put_contents('./public_login.txt', date("Y-m-d H:i:s").' ：'.json_encode($postArr).' ; '.PHP_EOL, FILE_APPEND);

        $qrcodeResult = self::curlRequest($qrcodeUrl, 'POST', json_encode($postArr));
        $qrcodeData = json_decode($qrcodeResult, true);

        if (empty($qrcodeData['url'])) {
            return false;
        }
        return $qrcodeData['url'];
    }

    /**
     * 生成二维码
     * @param $content  需要生成的二维码内容
     * @param $src  保存的地址.png结尾 (绝对路径)
     * @param $size  需要生成二维码的大小  12
     */
    public static function createQrcode($content, $src, $size)
    {
        $qrcode = new \dh2y\qrcode\QRcode();

        try {
            $result = $qrcode->png($content, $src, $size, 'L')->entry();;

        } catch (\Exception $e) {
            dump($e->getMessage());
        }

        if (file_exists($src)) {
            return $result;
        } else {
            return false;
        }
    }

    /**
     * 获取微信公众号accessToken
     *
     * @param $appId 微信公众号appId
     * @param $appSecret 微信公众号appSecret
     * @param $id 微信公众号Id
     * @return string
     */
    public static function getWechatOfficialAccountAccessToken($appId, $appSecret, $id)
    {
        $redis = Cache::store('redis')->handler();

        $redisKey = config('redis_key.get_wechat_official_account_access_token').$id;

        $accessToken = $redis->get($redisKey);

        if (empty($accessToken)) {
            // 获取access_token
            $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appId.'&secret='.$appSecret;
            $data = self::curlRequest($url, 'GET');
            $result = json_decode($data, true);

            if (empty($result['access_token'])) {
                return '';
            }

            $accessToken = $result['access_token'];

            $expire = config('redis_key.wechat_official_account_access_token_expire');

            $redis->set($redisKey, $accessToken, $expire);
        }

        return $accessToken;
    }

    // 检测一个目录是否存在 不存在则创建
    public static function mkdirChmod($path)
    {
        if(!is_readable($path))
        {
            is_file($path) or mkdir($path,0700);
        }
    }

    // curlpost请求
    public static function httpPost($url, $data)
    {
        // 初始化curl
        $ch = curl_init($url);

        // 配置一些参数
        curl_setopt($ch, CURLOPT_URL, $url);

        curl_setopt($ch,CURLOPT_POST, 0);

        curl_setopt($ch,CURLOPT_POSTFIELDS, $data); //这里的操作是上传文件，因此按照公众号开发者文档提到的，POST参数为 'media'

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

        $result = json_decode(curl_exec($ch), true); //将得到的结果转成数组输出，json_decode()解码

        if (curl_error($ch)) {
            return curl_errno($ch);
        }
        return $result;
    }

    /**
     * 获取微信小程序accessToken
     *
     * @param $appId 微信小程序appId
     * @param $appSecret 微信小程序appSecret
     * @param $id 微信小程序Id
     * @return string
     */
    public static function getWechatAppletAccessToken($appId, $appSecret, $id)
    {
        $redis = Cache::store('redis')->handler();
        $redis->select(5);
        $redisKey = config('redis_key.get_wechat_applet_access_token').$id;

        $accessToken = $redis->get($redisKey);

        if (empty($accessToken)) {
            // 获取access_token
            $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appId.'&secret='.$appSecret;
            $data = self::curlRequest($url);
            $result = json_decode($data, true);

            if (empty($result['access_token'])) {
                return '';
            }

            $accessToken = $result['access_token'];

            $expire = config('redis_key.wechat_applet_access_token_expire');

            $redis->set($redisKey, $accessToken, $expire);
        }

        return $accessToken;
    }

    /**
     * 获取稳定版接口调用凭据
     * 微信小程序accessToken
     *
     * @param $appId 微信小程序appId
     * @param $appSecret 微信小程序appSecret
     * @param $id 微信小程序Id
     * @return string
     */
    public static function getWechatAppletStableAccessToken($appId, $appSecret, $id)
    {
        $redis = Cache::store('redis')->handler();
        $redis->select(5);
        $redisKey = config('redis_key.get_wechat_applet_stable_access_token').$id;

        $accessToken = $redis->get($redisKey);

        if (empty($accessToken)) {
            // 获取access_token
            $url = 'https://api.weixin.qq.com/cgi-bin/stable_token';
            $requestBody = [
                'grant_type' => 'client_credential',
                'appid' => $appId,
                'secret' => $appSecret,
            ];
            $data = self::curlPostRequest($url,json_encode($requestBody));
            $result = json_decode($data, true);

            if (empty($result['access_token'])) {
                return '';
            }

            $accessToken = $result['access_token'];

            $expire = config('redis_key.wechat_applet_stable_access_token_expire');

            $redis->set($redisKey, $accessToken, $expire);
        }

        return $accessToken;
    }

    // 快手获取AccessToken
    public static function getKwaiAccessToken($appId, $secret)
    {
        $redis = Cache::store('redis')->handler();
        $redis->select(5);

        $accessToken = $redis->get(config('kwai.magnetic_force_access_token'));

        if (empty($accessToken)) {
            $refreshToken = $redis->get(config('kwai.magnetic_force_refresh_token'));
            $url = 'https://ad.e.kuaishou.com/rest/openapi/oauth2/authorize/refresh_token';
            $requestData = [
                'app_id' => $appId,
                'secret' => $secret,
                'refresh_token' => $refreshToken
            ];

            $result = self::curlRequest($url, 'POST', json_encode($requestData), ['Content-Type: application/json']);
            $result = json_decode($result, true);

            if ($result['code']) {
                return ['message' => $result['message']];
            }

            $redis->set(config('kwai.magnetic_force_access_token'), $result['data']['access_token'], $result['data']['access_token_expires_in']);
            $redis->set(config('kwai.magnetic_force_refresh_token'), $result['data']['refresh_token'], $result['data']['refresh_token_expires_in']);
            // $redis->set(config('kwai.magnetic_force_advertiser_ids'), json_encode($result['data']['advertiser_ids']), $result['data']['access_token_expires_in']);
            $accessToken = $result['data']['access_token'];
        }

        return $accessToken;
    }

    // 抖音巨量获取AccessToken
    public static function getHugeAmountAccessToken($appId, $secret)
    {
        $redis = Cache::store('redis')->handler();
        $redis->select(5);
        if ($appId == config('tiktok.huge_amount_yaodao.app_id') || $appId == config('tiktok.huge_amount_xingcan.app_id') || $appId == config('tiktok.huge_amount_sixseals_erfen.app_id')) {
            $accessToken = $redis->get(config('redis_key.huge_amount_access_token').'-'.$appId);
        } else {
            $accessToken = $redis->get(config('redis_key.huge_amount_access_token'));
        }

        if (empty($accessToken)) {
            if ($appId == config('tiktok.huge_amount_yaodao.app_id') || $appId == config('tiktok.huge_amount_xingcan.app_id') || $appId == config('tiktok.huge_amount_sixseals_erfen.app_id')) {
                $refreshToken = $redis->get(config('redis_key.huge_amount_refresh_token').'-'.$appId);
            } else {
                $refreshToken = $redis->get(config('redis_key.huge_amount_refresh_token'));
            }

            $url = 'https://ad.oceanengine.com/open_api/oauth2/refresh_token/';
            $requestData = [
                'app_id' => $appId,
                'secret' => $secret,
                'grant_type' => 'refresh_token',
                'refresh_token' => $refreshToken
            ];
            $result = self::curlRequest($url, 'POST', json_encode($requestData), ['Content-Type: application/json']);

            $result = json_decode($result, true);

            if ($result['code']) {
                return ['message' => $result['message']];
            }

            if ($appId == config('tiktok.huge_amount_yaodao.app_id') || $appId == config('tiktok.huge_amount_xingcan.app_id') || $appId == config('tiktok.huge_amount_sixseals_erfen.app_id')) {
                $redis->set(config('redis_key.huge_amount_access_token').'-'.$appId, $result['data']['access_token'], $result['data']['expires_in']);
                $redis->set(config('redis_key.huge_amount_refresh_token').'-'.$appId, $result['data']['refresh_token'], $result['data']['refresh_token_expires_in']);
            } else {
                $redis->set(config('redis_key.huge_amount_access_token'), $result['data']['access_token'], $result['data']['expires_in']);
                $redis->set(config('redis_key.huge_amount_refresh_token'), $result['data']['refresh_token'], $result['data']['refresh_token_expires_in']);
            }

            $accessToken = $result['data']['access_token'];
        }

        return $accessToken;
    }

    // 大连亦书主体获取AccessToken
    // public static function getHugeAmountYishuAccessToken()
    // {
    //     $redis = Cache::store('redis')->handler();
    //     $redis->select(5);
    // }

    // 获取百度AccessToken
    public static function getBaiduAccessToken()
    {
        $redis = Cache::store('redis')->handler();
        $redis->select(5);

        $accessToken = $redis->get(config('baidu.access_token'));

        if (empty($accessToken)) {
            $refreshToken = $redis->get(config('baidu.refresh_token'));
            $url = 'https://u.baidu.com/oauth/refreshToken';
            $appId = config('baidu.app_id');
            $secret = config('baidu.secret_key');
            $userId = $redis->get(config('baidu.baidu_user_id'));

            $requestData = [
                'appId' => $appId,
                'secretKey' => $secret,
                'userId' => $userId,
                'refreshToken' => $refreshToken
            ];
            $result = self::curlRequest($url, 'POST', json_encode($requestData), ['Content-Type: application/json']);

            $result = json_decode($result, true);

            if ($result['code']) {
                return ['message' => $result['message']];
            }

            $redis->set(config('baidu.access_token'), $result['data']['accessToken'], $result['data']['expiresIn']);
            $redis->set(config('baidu.refresh_token'), $result['data']['refreshToken'], $result['data']['refreshExpiresIn']);
            $redis->set(config('baidu.open_id'), $result['data']['openId'], $result['data']['refreshExpiresIn']);
            $accessToken = $result['data']['accessToken'];
        }

        return $accessToken;
    }

    // 快手小程序接口调用凭证
    public static function getKwaiAppletAccessToken($appId, $secret)
    {
        $redis = Cache::store('redis')->handler();
        $redis->select(5);

        $accessToken = $redis->get(config('kwai.applet_access_token').$appId);

        if (empty($accessToken)) {
            $url = 'https://open.kuaishou.com/oauth2/access_token';

            $requestData = [
                'app_id' => $appId,
                'app_secret' => $secret,
                'grant_type' => 'client_credentials'
            ];

            $result = self::curlGetRequest($url, http_build_query($requestData), ['Content-type:application/x-www-form-urlencoded;charset=UTF-8']);
            $result = json_decode($result, true);

            if ($result['result'] != 1) {
                return ['message' => $result['message']];
            }

            $redis->set(config('kwai.applet_access_token').$appId, $result['access_token'], $result['expires_in']);

            $accessToken = $result['access_token'];
        }

        return $accessToken;
    }

    // 微博监测地址
    public static function getWeiboAccessToken()
    {
        $redis = Cache::store('redis')->handler();
        $redis->select(5);

        $accessToken = $redis->get(config('weibo.applet_access_token'));

        if (empty($accessToken)) {
            $refreshToken = $redis->get(config('weibo.applet_refresh_token'));
            $url = 'https://api.biz.weibo.com/oauth/token';
            $appId = config('weibo.app_id');

            if (empty($refreshToken)) {

                $code = $redis->get(config('weibo.callback_code'));

                $requestData = [
                    'client_id' => $appId,
                    'grant_type' => 'authorization_code',
                    'redirect_uri' => 'https://shortplay.sybyn.top/cps/link/weiboCallback',
                    'code' => $code
                ];

                $url = $url . '?' . http_build_query($requestData);
                $result = self::curlRequest($url, 'GET');
                $result = json_decode($result, true);

                // if ($result['result'] != 1) {
                //     return ['message' => $result['message']];
                // }

                $redis->set(config('weibo.applet_access_token'), $result['access_token'], $result['expires_in']);
                $redis->set(config('weibo.applet_refresh_token'), $result['refresh_token'], $result['refresh_expires_in']);

                $accessToken = $result['access_token'];
            } else {
                $requestData = [
                    'client_id' => $appId,
                    'grant_type' => 'refresh_token',
                    'refresh_token' => $refreshToken
                ];

                $url = $url . '?' . http_build_query($requestData);
                $result = self::curlRequest($url, 'GET');
                $result = json_decode($result, true);

                $redis->set(config('weibo.applet_access_token'), $result['access_token'], $result['expires_in']);
                // $redis->set(config('weibo.applet_refresh_token'), $result['refresh_token'], $result['refresh_expires_in']);

                $accessToken = $result['access_token'];
            }
        }

        return $accessToken;
    }

    // 获取腾讯广告平台开发者应用的accessToken
    public static function getTencentAdDeveloperAppAccessToken($developerInfo)
    {
        $redis = Cache::store('redis')->handler();
        $redis->select(5);

        $accessToken = $redis->get(config('tencent.developer_access_token'));

        if (empty($accessToken)) {
            $refreshToken = $redis->get(config('tencent.developer_refresh_token'));
            $url = 'https://api.e.qq.com/oauth/token';

            if (empty($refreshToken)) {
                return '';
            } else {
                $requestData = [
                    'client_id' => $developerInfo['client_id'],
                    'client_secret' => $developerInfo['client_secret'],
                    'grant_type' => 'refresh_token',
                    'refresh_token' => $refreshToken
                ];

                $url = $url . '?' . http_build_query($requestData);
                $result = self::curlRequest($url, 'GET');
                $tencentData = json_decode($result, true);

                $redis->set(config('tencent.developer_access_token'),  $tencentData['data']['access_token'],  $tencentData['data']['access_token_expires_in']);

                $accessToken = $tencentData['data']['access_token'];
            }
        }

        return $accessToken;
    }

    // 获取抖音开发者平台接口调用的凭证client_token 适用于抖音授权
    public static function getTikTokDeveloperClientToken($appId = 'tt716807d5ee55bba601', $secret = '42803a89cef2a81970e4cc92e147385a75422d7c')
    {
        $redis = Cache::store('redis')->handler();
        $redis->select(5);
        $tiktok_config = config('tiktok.developer') ?: [];
        $clientKey = $tiktok_config['client_token_key'] . '_' . $appId;
        $clientToken = $redis->get($clientKey);

        if (empty($clientToken)) {
            $env = env('app.app_env', 'sandbox');
            $requestUrl = $env == 'prod' ? 'https://open.douyin.com/oauth/client_token/' : 'https://open-sandbox.douyin.com/oauth/client_token/';
            $data = [
                'client_key' => $appId,
                'client_secret' => $secret,
                'grant_type' => 'client_credential'
            ];

            $result = self::curlRequest($requestUrl, 'POST', json_encode($data), ['Content-Type: application/json']);

            // dump($result);die;
            $clientTokenData = json_decode($result, true);
            if (!$clientTokenData || empty($clientTokenData['data']['access_token'])) {
                return '';
            }

            $redis->set($clientKey, $clientTokenData['data']['access_token'], $tiktok_config['client_token_expire']);

            $clientToken = $clientTokenData['data']['access_token'];
        }
        return $clientToken;
    }
    /**
     * 雪花算法
     * @param string $key
     * @return string
     * @throws \Exception
     */
    public static function Snowflake(){
        if(class_exists(\wantp\Snowflake\IdWorker::class)){
            $dataCenterId = env('SNOWFLAKE.CENTERID',1);
            $machineId = env('SNOWFLAKE.MACHINEID',1);
            try{
                $IdWorker = \wantp\Snowflake\IdWorker::getIns($dataCenterId,$machineId);
                $id = $IdWorker->id();
            }catch(\Exception $e){
                $id = date('YmdHis') . rand(1000, 10000);
            }
        }else{
            $id = date('YmdHis') . rand(1000, 10000);
        }
        return $id;
    }
}